package com.albertattard.jff;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle;
import javax.swing.border.Border;

/**
 * 
 * @author aattard
 * 
 */
@SuppressWarnings("serial")
public class Application extends JFrame {

	/** */
	private static final Border ERROR_BORDER = BorderFactory.createLineBorder(
			Color.RED, 2);
	/** */
	private JTextField classFullNameTextField;
	/** */
	private JTextArea directoriesTextArea;
	/** */
	private Border originalBorder1;
	/** */
	private Border originalBorder2;
	/** */
	private JProgressBar progressBar;
	/** */
	private JTextArea resultsTextArea;
	/** */
	private JScrollPane scrollPane1;
	/** */
	private JButton searchButton;

	/**
	 * 
	 */
	public Application() {
		initComponents();
	}

	/**
	 * 
	 */
	private void initComponents() {
		final GroupLayout thisLayout = new GroupLayout(getContentPane());
		setLayout(thisLayout);
		setPreferredSize(new Dimension(600, 400));

		final JLabel classFullNameLabel = new JLabel("Class Full Name");
		classFullNameTextField = new JTextField("java.lang.String");
		originalBorder1 = classFullNameTextField.getBorder();
		classFullNameTextField
				.setToolTipText("The class name preceded by the package. For example: java.lang.String");

		final JLabel directoriesLabel = new JLabel("Directories");
		directoriesTextArea = new JTextArea("c:\ng:");
		directoriesTextArea
				.setToolTipText("The directories where to search for Jar files. Enter a directory per line and you do not have to provide quotes.");
		scrollPane1 = new JScrollPane(directoriesTextArea);
		originalBorder2 = scrollPane1.getBorder();

		searchButton = new JButton("Search");
		searchButton.setToolTipText("Click to start the search");
		searchButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				if (validateInput()) {
					search();
				}
			}
		});

		progressBar = new JProgressBar();
		progressBar.setStringPainted(true);
		progressBar.setVisible(false);

		resultsTextArea = new JTextArea();
		resultsTextArea
				.setToolTipText("The list of Jar files where the class is found will be listed here");
		resultsTextArea.setEditable(false);
		final JScrollPane scrollPane2 = new JScrollPane(resultsTextArea);

		thisLayout.setVerticalGroup(thisLayout.createSequentialGroup()
				.addContainerGap().addGroup(
						thisLayout.createParallelGroup(
								GroupLayout.Alignment.BASELINE).addComponent(
								classFullNameTextField,
								GroupLayout.Alignment.BASELINE,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE).addComponent(
								classFullNameLabel,
								GroupLayout.Alignment.BASELINE,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED).addGroup(
						thisLayout.createParallelGroup().addGroup(
								GroupLayout.Alignment.LEADING,
								thisLayout.createSequentialGroup()
										.addComponent(directoriesLabel,
												GroupLayout.PREFERRED_SIZE,
												GroupLayout.PREFERRED_SIZE,
												GroupLayout.PREFERRED_SIZE)
										.addGap(64)).addComponent(scrollPane1,
								GroupLayout.Alignment.LEADING,
								GroupLayout.PREFERRED_SIZE, 80,
								GroupLayout.PREFERRED_SIZE)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED).addGroup(
						thisLayout.createParallelGroup().addComponent(
								searchButton, GroupLayout.Alignment.LEADING,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE,
								GroupLayout.PREFERRED_SIZE).addComponent(
								progressBar, GroupLayout.Alignment.LEADING,
								GroupLayout.PREFERRED_SIZE, 26,
								GroupLayout.PREFERRED_SIZE)).addPreferredGap(
						LayoutStyle.ComponentPlacement.UNRELATED, 1,
						GroupLayout.PREFERRED_SIZE).addComponent(scrollPane2,
						0, 149, Short.MAX_VALUE).addContainerGap());
		thisLayout
				.setHorizontalGroup(thisLayout
						.createSequentialGroup()
						.addContainerGap()
						.addGroup(
								thisLayout
										.createParallelGroup()
										.addGroup(
												thisLayout
														.createSequentialGroup()
														.addGroup(
																thisLayout
																		.createParallelGroup()
																		.addComponent(
																				directoriesLabel,
																				GroupLayout.Alignment.LEADING,
																				GroupLayout.PREFERRED_SIZE,
																				104,
																				GroupLayout.PREFERRED_SIZE)
																		.addComponent(
																				classFullNameLabel,
																				GroupLayout.Alignment.LEADING,
																				GroupLayout.PREFERRED_SIZE,
																				104,
																				GroupLayout.PREFERRED_SIZE))
														.addGap(12)
														.addGroup(
																thisLayout
																		.createParallelGroup()
																		.addGroup(
																				GroupLayout.Alignment.LEADING,
																				thisLayout
																						.createSequentialGroup()
																						.addGap(
																								0,
																								0,
																								Short.MAX_VALUE)
																						.addComponent(
																								progressBar,
																								GroupLayout.PREFERRED_SIZE,
																								200,
																								GroupLayout.PREFERRED_SIZE)
																						.addPreferredGap(
																								LayoutStyle.ComponentPlacement.UNRELATED,
																								1,
																								GroupLayout.PREFERRED_SIZE)
																						.addComponent(
																								searchButton,
																								GroupLayout.PREFERRED_SIZE,
																								78,
																								GroupLayout.PREFERRED_SIZE))
																		.addComponent(
																				scrollPane1,
																				GroupLayout.Alignment.LEADING,
																				0,
																				266,
																				Short.MAX_VALUE)
																		.addComponent(
																				classFullNameTextField,
																				GroupLayout.Alignment.LEADING,
																				0,
																				266,
																				Short.MAX_VALUE)))
										.addComponent(scrollPane2,
												GroupLayout.Alignment.LEADING,
												0, 382, Short.MAX_VALUE))
						.addGap(6));
	}

	/**
	 * 
	 */
	private void search() {
		progressBar.setValue(0);
		progressBar.setVisible(true);
		progressBar.setIndeterminate(true);
		searchButton.setEnabled(false);
		resultsTextArea.setText("");

		final String[] directoriesList = directoriesTextArea.getText().split(
				"\\n");
		final String classFullName = classFullNameTextField.getText();

		final JarFinderWorker worker = new JarFinderWorker(directoriesList,
				classFullName) {
			@Override
			protected void done() {
				progressBar.setVisible(false);
				searchButton.setEnabled(true);
				try {
					final List<String> list = get();
					int size = 0;
					if (list != null) {
						size = list.size();
					}
					resultsTextArea.append("\n");
					resultsTextArea.append("\n");
					resultsTextArea.append("Search complete\n");
					resultsTextArea.append("Files matched: " + size);
				} catch (final Exception e) {
					e.printStackTrace();
					resultsTextArea.append(e.getLocalizedMessage());
				}
				resultsTextArea.append("\n");
				resultsTextArea.setCaretPosition(resultsTextArea.getText()
						.length());
			}

			@Override
			protected void process(final List<String> chunks) {
				for (final String chunk : chunks) {
					resultsTextArea.append(chunk);
					resultsTextArea.append("\n");
					resultsTextArea.setCaretPosition(resultsTextArea.getText()
							.length());
				}
			}
		};
		worker.execute();

		final PropertyChangeListener listener = new PropertyChangeListener() {
			public void propertyChange(final PropertyChangeEvent event) {
				if ("progress".equals(event.getPropertyName())) {
					progressBar.setIndeterminate(false);
					progressBar.setValue((Integer) event.getNewValue());
				}
			}
		};
		worker.addPropertyChangeListener(listener);
	}

	/**
	 * 
	 * @return
	 */
	private boolean validateInput() {
		resultsTextArea.setText("");

		boolean valid = true;
		classFullNameTextField.setBorder(originalBorder1);
		if (classFullNameTextField.getText().trim().length() == 0) {
			classFullNameTextField.setBorder(Application.ERROR_BORDER);
			resultsTextArea.append("The class full name cannot be empty\n");
			valid = false;
		}

		scrollPane1.setBorder(originalBorder2);
		final String[] directories = directoriesTextArea.getText().trim()
				.split("\\n");
		for (final String direcotry : directories) {
			if (!(new File(direcotry).isDirectory())) {
				if (direcotry.trim().length() == 0) {
					resultsTextArea
							.append("The empty directory path is not a valid\n");
				} else {
					resultsTextArea.append("The path '" + direcotry
							+ "' is not a valid directory\n");
				}
				scrollPane1.setBorder(Application.ERROR_BORDER);
				valid = false;
				break;
			}
		}

		return valid;
	}
}
